#include "../logs/log.h"
// c++11提供的时间特性
#include <chrono>
#include<vector>
#include<thread>
// 设计性能测试功能
// logger_name日志器的名字，thr_count线程数的个数，msg_counr日志消息的总条数，len日志消息的长度
void bench(const std::string &logger_name, size_t thr_count, size_t msg_count, size_t msg_len)
{
    // 1.获取日志器
    log::Logger::ptr logger = log::getLogger(logger_name);
    // 如果没找到日志器就返回空
    if (logger.get() == nullptr)
    {
        return;
    }
    // 2.组织指定长度的日志消息
    // 留一个字符，放换行符
    std::string msg(msg_len - 1, 'A');
    // 3.创建指定数量的线程
    // 创建一个存放线程的数组
    std::vector<std::thread> threads;
    // 存放每个线程打印日志需要消耗的时间
    std::vector<double> cost_arry(thr_count);
    // 每个线程需要打印的日志数=总日志数/线程数
    size_t msg_per_thr = msg_count / thr_count;
    // 创建指定数量的线程，push_back()构造然后拷贝，插入元素到末尾,emplace_back()构造并插入元素到末尾
    // 打印测试日志总条数，总大小
    std::cout << "\t测试日志：" << msg_count << "条，\t总大小:" << (msg_count * msg_len) / 1024 << "KB\n";
    for (int i = 0; i < thr_count; i++)
    {
        // 插入元素时用lambad表达式
        threads.emplace_back([&, i]()
                             {
            // 4.线程函数内部开始计时,高精度获得当前的系统时间
            auto start=std::chrono::high_resolution_clock::now();
            // 5.开始循环写日志
            for(int i=0;i<msg_per_thr;i++){
            //打印日志
            logger->fatal("%s",msg.c_str());
            }
            // 6.线程函数内部结束计时，高精度获得当前的系统时间
            auto end=std::chrono::high_resolution_clock::now();
            //每个线程需要的时间
            std::chrono::duration<double> cost=end-start;
            cost_arry[i]=cost.count();
            std::cout<<"\t线程"<<i<<"："<<"\t输出数量日志："<<msg_per_thr<<",\t耗时："<<cost.count()<<"s"<<std::endl; });
    }
    // 要记住，创建线程那么就要等待线程退出
    for (int i = 0; i < thr_count; i++)
    {
        threads[i].join();
    }
    // 7.计算总耗时：在多线程中，每个线程都会耗时间，但是线程是并发运行处理的，因此耗时最高的线程就是总时间。
    // 创建的子线程已经全部退出了
    double max_cost = cost_arry[0];
    for (int i = 0; i < thr_count; i++)
    {
        max_cost = max_cost < cost_arry[i] ? cost_arry[i] : max_cost;
    }
    // 每秒输出日志数量=总日志数/总消耗时间
    size_t msg_per_sec = msg_count / max_cost;
    // 每秒输出日志大小=日志数量*单条日志大小/总耗时，这里单位是kb(加了1024)
    size_t size_per_sec = (msg_count * msg_len) / (max_cost*1024);
    // 8.进行输出打印
    std::cout << "\t总耗时：" << max_cost << "s\n";
    std::cout << "\t每秒输出日志数量：" << msg_per_sec << "条\n";
    std::cout << "\t每秒输出日志大小：" << size_per_sec << "KB\n";
}

// 测试同步日志器
void sync_bench()
{
    // 创建一个同步日志器建造者
    std::unique_ptr<log::LoggerBuilder> builder(new log::GlobalLoggerBuilder());
    // 建造者构建零部件
    builder->buildLoggerName("sync_logger");
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(log::LoggerType::LOGGER_SYNC);
    builder->buildSink<log::FileSink>("./logfile/sync.log"); // 文件落地方式
    // builder->buildSink<log::StdoutSink>();                                   // 标准输出落地
    // builder->buildSink<log::RoolBySizeSink>("./logfile/roll-sync-", 1024 * 1024); // 滚动文件落地方式
    builder->build();
    //  测试单线程情况
    bench("sync_logger", 1, 1000000, 100);
}

// 测试异步日志器
void async_bench()
{
// 创建一个同步日志器建造者
    std::unique_ptr<log::LoggerBuilder> builder(new log::GlobalLoggerBuilder());
    // 建造者构建零部件
    builder->buildLoggerName("async_logger");
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(log::LoggerType::LOGGER_ASYNC);
    builder->buildEnableUnSafeAsync();//开启非安全模式————主要是为了将实际落地时间排除在外
    builder->buildSink<log::FileSink>("./logfile/async.log"); // 文件落地方式
    // builder->buildSink<log::StdoutSink>();                                   // 标准输出落地
    // builder->buildSink<log::RoolBySizeSink>("./logfile/roll-sync-", 1024 * 1024); // 滚动文件落地方式
    builder->build();
    //  测试单线程情况
    bench("async_logger", 1, 1000000, 100);

}



int main()
{	// 同步日志器单线程
    async_bench();
    return 0;
}
